package ws.jdbc.concurrent.driver.sqlserver.tds;

import java.io.IOException;
import java.nio.ByteBuffer;
import ws.jdbc.concurrent._development.DevMode;
import ws.jdbc.concurrent.driver.sqlserver.tds.datastreamtypes.VariableLengthDataStream;

/**
 * Handles the {@code ENVCHANGE} token reading process.
 *
 * <p>This token stream used to send a notification of an environment change
 * (for example, database, language, and so on).
 * </p>
 *
 * @author Wilson Santos, 36228 <wilson.santos@ua.pt>
 */
public class EnvChangeTokenReader extends TokenReader {

  /**
   * Type of environment change.
   *
   * See <a href=http://msdn.microsoft.com/en-us/library/dd303449(v=PROT.13).aspx>Token Stream Parameter Details</a>
   * for a list of environment change type.
   */
  private byte envType;
  /**
   * New value.
   */
  private VariableLengthDataStream newValue;
  /**
   * Old value.
   */
  private VariableLengthDataStream oldValue;

  /**
   * Create a new reader instance.
   *
   * @param stream data input stream to read the token from.
   */
  EnvChangeTokenReader(final ByteBuffer stream) {
    super(stream);
  }

  /**
   * Read one {@code ENVCHANGE} token.
   *
   * @return number of bytes read.
   *
   * @throws IOException if an error occurs while reading from the data input stream.
   */
  @Override
  int read() throws IOException {
    if (DevMode.concurrent_driver_sqlserver_tds) {
      DevMode.printlog(null);
    }
    // Length (USHORT)
    tokenLength = stream.getShort();
    // EnValueData
    //    Type (BYTE)
    envType = stream.get();
    //    NewValue (every Type has its own definition)
    newValue = readEnvNewValue(envType);
    //    OldValue (every Type has its own definition)
    oldValue = readEnvOldValue(envType);

    assert tokenLength + 2 == 3 + vldsReader.getBytesRead();

    return tokenLength + 2;
  }

  /**
   * Token as a {@code String}.
   *
   * @return token fields as a {@code String}.
   */
  @Override
  public String toString() {
    return "EnvChangeTokenReader{"
            + "\n  tokenLength=" + tokenLength
            + "\n  envType=" + envType
            + "\n  newValue=" + newValue
            + "\n  oldValue=" + oldValue
            + "\n}\n";
  }

  private VariableLengthDataStream readEnvNewValue(byte envType) throws IOException {
    if (DevMode.concurrent_driver_sqlserver_tds) {
      DevMode.printlog(null);
    }
    VariableLengthDataStream ret = null;
    switch (envType) {
      case 1:
      case 2:
      case 3:
      case 4:
      case 5:
      case 6:
      case 13:
      case 19:
        ret = vldsReader.readBVarChar();
        break;
      case 9:
      case 10:
      case 11:
      case 17:
      case 18:
        ret = null; // 0x00
        break;
      case 7:
      case 8:
      case 12:
      case 16:
        ret = vldsReader.readBVarByte();
        break;
      case 15:
        ret = vldsReader.readLVarByte();
        break;
    }
    return ret;
  }

  private VariableLengthDataStream readEnvOldValue(byte envType) throws IOException {
    if (DevMode.concurrent_driver_sqlserver_tds) {
      DevMode.printlog(null);
    }
    VariableLengthDataStream ret = null;
    switch (envType) {
      case 1:
      case 2:
      case 3:
      case 4:
        ret = vldsReader.readBVarChar();
        break;
      case 5:
      case 6:
      case 8:
      case 12:
      case 13:
      case 15:
      case 16:
      case 18:
      case 19:
        ret = null; // 0x00
        break;
      case 7:
      case 9:
      case 10:
      case 11:
      case 17:
        ret = vldsReader.readBVarByte();
        break;
    }
    return ret;
  }
}
